/**
 * 通用数据验证工具
 */

import type { ErrorDetail } from './error-handler'

// 验证结果接口
export interface ValidationResult {
  valid: boolean
  errors: ErrorDetail[]
}

// 验证规则接口
export interface ValidationRule {
  required?: boolean
  min?: number
  max?: number
  minLength?: number
  maxLength?: number
  pattern?: RegExp
  email?: boolean
  url?: boolean
  phone?: boolean
  custom?: (value: any) => boolean | string
  message?: string
}

// 验证器类
class Validator {
  // 验证单个字段
  validateField(value: any, rules: ValidationRule, fieldName: string): ErrorDetail[] {
    const errors: ErrorDetail[] = []

    // 必填验证
    if (rules.required && this.isEmpty(value)) {
      errors.push({
        msg: rules.message || `${fieldName}不能为空`,
        param: fieldName
      })
      return errors // 如果必填验证失败，不继续其他验证
    }

    // 如果值为空且不是必填，跳过其他验证
    if (this.isEmpty(value) && !rules.required) {
      return errors
    }

    // 最小值验证
    if (rules.min !== undefined && typeof value === 'number' && value < rules.min) {
      errors.push({
        msg: rules.message || `${fieldName}不能小于${rules.min}`,
        param: fieldName
      })
    }

    // 最大值验证
    if (rules.max !== undefined && typeof value === 'number' && value > rules.max) {
      errors.push({
        msg: rules.message || `${fieldName}不能大于${rules.max}`,
        param: fieldName
      })
    }

    // 最小长度验证
    if (rules.minLength !== undefined && typeof value === 'string' && value.length < rules.minLength) {
      errors.push({
        msg: rules.message || `${fieldName}长度不能少于${rules.minLength}个字符`,
        param: fieldName
      })
    }

    // 最大长度验证
    if (rules.maxLength !== undefined && typeof value === 'string' && value.length > rules.maxLength) {
      errors.push({
        msg: rules.message || `${fieldName}长度不能超过${rules.maxLength}个字符`,
        param: fieldName
      })
    }

    // 正则表达式验证
    if (rules.pattern && typeof value === 'string' && !rules.pattern.test(value)) {
      errors.push({
        msg: rules.message || `${fieldName}格式不正确`,
        param: fieldName
      })
    }

    // 邮箱验证
    if (rules.email && typeof value === 'string' && !this.isValidEmail(value)) {
      errors.push({
        msg: rules.message || `${fieldName}邮箱格式不正确`,
        param: fieldName
      })
    }

    // URL验证
    if (rules.url && typeof value === 'string' && !this.isValidUrl(value)) {
      errors.push({
        msg: rules.message || `${fieldName}URL格式不正确`,
        param: fieldName
      })
    }

    // 手机号验证
    if (rules.phone && typeof value === 'string' && !this.isValidPhone(value)) {
      errors.push({
        msg: rules.message || `${fieldName}手机号格式不正确`,
        param: fieldName
      })
    }

    // 自定义验证
    if (rules.custom) {
      const result = rules.custom(value)
      if (result !== true) {
        errors.push({
          msg: typeof result === 'string' ? result : (rules.message || `${fieldName}验证失败`),
          param: fieldName
        })
      }
    }

    return errors
  }

  // 验证对象
  validateObject(data: Record<string, any>, schema: Record<string, ValidationRule>): ValidationResult {
    const errors: ErrorDetail[] = []

    for (const [fieldName, rules] of Object.entries(schema)) {
      const fieldErrors = this.validateField(data[fieldName], rules, fieldName)
      errors.push(...fieldErrors)
    }

    return {
      valid: errors.length === 0,
      errors
    }
  }

  // 检查值是否为空
  private isEmpty(value: any): boolean {
    if (value === null || value === undefined) return true
    if (typeof value === 'string') return value.trim() === ''
    if (Array.isArray(value)) return value.length === 0
    if (typeof value === 'object') return Object.keys(value).length === 0
    return false
  }

  // 验证邮箱格式
  private isValidEmail(email: string): boolean {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
    return emailRegex.test(email)
  }

  // 验证URL格式
  private isValidUrl(url: string): boolean {
    try {
      new URL(url)
      return true
    } catch {
      return false
    }
  }

  // 验证手机号格式（中国大陆）
  private isValidPhone(phone: string): boolean {
    const phoneRegex = /^1[3-9]\d{9}$/
    return phoneRegex.test(phone)
  }
}

// 创建全局验证器实例
export const validator = new Validator()

// 常用验证规则
export const commonRules = {
  required: { required: true },
  email: { email: true },
  url: { url: true },
  phone: { phone: true },
  
  // 用户名规则
  username: {
    required: true,
    minLength: 3,
    maxLength: 20,
    pattern: /^[a-zA-Z0-9_]+$/,
    message: '用户名只能包含字母、数字和下划线，长度3-20个字符'
  },
  
  // 密码规则
  password: {
    required: true,
    minLength: 6,
    maxLength: 20,
    message: '密码长度必须在6-20个字符之间'
  },
  
  // 强密码规则
  strongPassword: {
    required: true,
    minLength: 8,
    maxLength: 20,
    pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]/,
    message: '密码必须包含大小写字母、数字和特殊字符，长度8-20个字符'
  },
  
  // 标题规则
  title: {
    required: true,
    minLength: 1,
    maxLength: 100,
    message: '标题长度必须在1-100个字符之间'
  },
  
  // 描述规则
  description: {
    maxLength: 500,
    message: '描述长度不能超过500个字符'
  },
  
  // 内容规则
  content: {
    required: true,
    minLength: 10,
    message: '内容不能少于10个字符'
  },
  
  // 分类ID规则
  categoryId: {
    required: true,
    min: 1,
    custom: (value: any) => Number.isInteger(value) && value > 0,
    message: '请选择有效的分类'
  },
  
  // 标签规则
  tags: {
    custom: (value: any) => {
      if (!Array.isArray(value)) return '标签必须是数组格式'
      if (value.length > 10) return '标签数量不能超过10个'
      return value.every(tag => typeof tag === 'string' && tag.trim().length > 0) || '标签格式不正确'
    }
  },
  
  // 图片URL规则
  imageUrl: {
    url: true,
    pattern: /\.(jpg|jpeg|png|gif|webp)$/i,
    message: '请提供有效的图片URL'
  },
  
  // 排序规则
  sort: {
    min: 0,
    max: 9999,
    custom: (value: any) => Number.isInteger(value),
    message: '排序必须是0-9999之间的整数'
  }
}

// 便捷的验证函数
export const validate = {
  field: (value: any, rules: ValidationRule, fieldName: string) => 
    validator.validateField(value, rules, fieldName),
  
  object: (data: Record<string, any>, schema: Record<string, ValidationRule>) => 
    validator.validateObject(data, schema),
  
  // 验证课程数据
  lesson: (data: any) => validator.validateObject(data, {
    title: commonRules.title,
    description: commonRules.description,
    content: commonRules.content,
    categoryId: commonRules.categoryId,
    tags: commonRules.tags,
    coverImage: { ...commonRules.imageUrl, required: false },
    difficulty: {
      required: true,
      custom: (value: any) => ['beginner', 'intermediate', 'advanced'].includes(value),
      message: '难度必须是 beginner、intermediate 或 advanced'
    }
  }),
  
  // 验证分类数据
  category: (data: any) => validator.validateObject(data, {
    name: commonRules.title,
    description: { ...commonRules.description, required: false },
    parentId: {
      min: 0,
      custom: (value: any) => value === null || (Number.isInteger(value) && value >= 0),
      message: '父分类ID必须是有效的数字'
    },
    sort: commonRules.sort
  }),
  
  // 验证用户数据
  user: (data: any) => validator.validateObject(data, {
    username: commonRules.username,
    email: { ...commonRules.email, required: true },
    password: commonRules.password
  }),
  
  // 验证登录数据
  login: (data: any) => validator.validateObject(data, {
    username: { required: true, minLength: 1, message: '请输入用户名' },
    password: { required: true, minLength: 1, message: '请输入密码' }
  })
}

export default validator 